//
//  main.m
//  OC02_实例变量可见度_方法
//
//  Created by dllo on 16/2/25.
//  Copyright © 2016年 Apon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {

#pragma mark - 知识点1. 实例(成员)变量可见度
/** 
 * 3种: @public, @protected, @private
 * 默认: @protected
 *
 * 3种之间的区别: @public: 本类 可以直接访问(->).
                         子类 可以直接访问.
                         其他类 可以直接访问
                @protected: 本类 可以直接访问.
                            子类 可以直接访问.
                            其他类 不可以直接访问.
                @private: 本类 可以直接访问.
                          子类 不可以直接访问.
                          其他类 不可以直接访问.
 *详见 Person.h 文件.
 */
    
    
#pragma mark - 知识点2. 方法
/**
 * [接受者 消息]
 *
 * 接受者: 类和对象
 * 消息(方法): 类方法和对象方法.
 *
 * 详见 Person.h 文件.
 */

#if 0
    
#pragma mark - 知识点3. setter,getter方法
/**
 * 一个实例变量要有一对setter, getter方法.
 * setter方法目的, 对实例变量赋值.
 * getter方法目的, 对实例变量取值.
 *
 * 详见: Person.h 文件.
 */
    
    // 创建对象.
    Person *person1 = [[Person alloc] init];
    
    // 调用setter方法
    [person1 setName:@"zhangsan"];
    
    // 调用getter方法
    
    NSString *str = [person1 name];
    
    NSLog(@"str: %@", str);
    
    
    // 创建person2对象.
    Person *person2 = [[Person alloc] init];
    
    [person2 setName:@"Tom"];
    
    [person2 setName:@"Lisi"];
    
    NSLog(@"person2 = %@", [person2 name]);
    
    
    
    // 注意: 下面的person3并没有开辟新的内存空间, 只是指针指向了person2内存首地址
    
    Person *person3 = person2;
    
    NSLog(@"%@", [person3 name]);
    
    
#pragma mark - 知识点4. 继承.


/** 
 * 子类继承父类 所有的实例变量和方法.
 * OC中,只有子类和父类两层.
 * OC中是单向继承.
 * 继承有传递性.
 *
 *Student类继承于Person类, CollegeStudent类继承于Student类.
 *详见 Student, CollegeStudent类文件.
 */
    
    // 创建学生对象.
    Student *stu1 = [[Student alloc] init];
    
    // setName方法是从父类继承下来的的方法.
    [stu1 setName:@"wangwu"];

    [stu1 name:@"小明" sex:@"male" age:18];
    
    [stu1 sayHai];
    
    

    
    
#pragma mark - 知识点5. 重写父类方法(overwrite)
    /** 
     * 父类方法无法满足子类需求.
     * 重写父类方法一般是在父类方法的基础上, 添加新的代码段.
     *
     * 详见 Student.m 文件
     */
    
    // 创建一个student对象.
    Student *student1 = [[Student alloc] init];
    [student1 name:@"wangwu" sex:@"male" age:20];
    [student1 setGrade:80];
    [student1 setClassroomName:@"DLS160101"];
    
    
    // 调用sayHai方法.
    [student1 sayHai];
    
    
#pragma mark - 知识点6. 重写初始化方法.
/** 
 * Person类 重写 父类的init方法.
 *
 * 详见 Person.m 文件.
 */
    
    
    // 创建一个Person对象.
    Person *person1 = [[Person alloc] init];
    [person1 sayHai];
    
    // 创建student对象.
    Student *stu = [[Student alloc] init];
    [stu sayHai];
  

#pragma mark - 知识点7. 自定义初始化方法
/** 
 * 需求: 通过一个方法, 实现了初始化, 同时给某些实例变量赋值.
 *
 * 详见 Person.h, Person.m文件.
 */
    
    // 创建person对象.
    Person *per1 = [[Person alloc] initWithName:@"Tom"];
    
    [per1 sayHai];
    
    
    Person *per2 = [[Person alloc] initWithName:@"zhangsan" sex:@"male" age:20];
    
    [per2 sayHai];
#endif
#pragma mark - 知识点8. 构造器
    /** 
     * 构造器就是方法.
     * + 方法.
     * 封装了对象创建和初始化过程.
     *
     * 详见 Person类文件.
     */
    
    // 创建对象.
    Person *per1 = [Person person];
    [per1 sayHai];
    
    Person *per2 = [Person personWithName:@"刘鸣" sex:@"女" age:50];
    [per2 sayHai];
    
    
    return 0;
}
